var db = require('bookshelf').bookshelf;
var Database = require('../app/database');
var moment = require('moment');
var Router = require('../app/router');
var util = require('util');

var UserController = module.exports = {};

log = function(msg) {
    //console.log(new Date().toLocaleTimeString() + ' [user_controller]: ' + msg);
};

UserController.initialize = function(router) {
	router
	.add({ Method: router.Methods.GET, URL: 'users/:id/sessions', Authorize: router.Access.Public, Handler: UserController.getSession })
	.add({ Method: router.Methods.GET, URL: 'users/sessions', Authorize: router.Access.Public, Handler: UserController.getSession })
	.add({ Method: router.Methods.GET, URL: 'users/:id', Authorize: router.Access.User, Handler: UserController.getUser })
    .add({ Method: router.Methods.GET, URL: 'users', Authorize: router.Access.Admin, Handler: UserController.getUsers})
	.add({ Method: router.Methods.POST, URL: 'users/:id', Authorize: router.Access.Registered, Handler: UserController.postUserSelf })
	.add({ Method: router.Methods.POST, URL: 'users', Authorize: router.Access.Admin, Handler: UserController.postUser })
	log('user_controller.js: ' + util.inspect(router,false,null));
};

UserController.getUsers = function(req, res) {
    log('GetUsers: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
    log('GetUsers: ' + req.originalUrl + ' : ' + util.inspect(req.query, { showHidden: true, depth: null }));
    
    var resolved = false;
    if (!resolved && req.query && req.query.login && req.query.login.length > 0) {
        resolved = true;
        var login = '';
        if (req.query && req.query.login.length > 0) {
            login = req.query.login;
        };
        if (login == '') {
            res.send(404, { user: req.session.user });
        } else {
            login = login.toLocaleLowerCase();
            new Database.Models.User({ login: login })
		        .query(function (qb) {
		            qb.where('login', 'like', '%' + login + '%') //.andWhere('is_active', '!=', '0');
		        })
                .then(function (resp) {
                    if (resp != null && resp.length && resp.length > 0) {
                        for (var i = 0; i < resp.length; i++){
                            var user = resp.at(i);
                            user.cleanUp();
                            log(util.inspect(user,false,null));
                        };
                    };
                    res.json(200, resp);
                    log('replied: ' + util.inspect(resp, false, null));
                });
        };
    };
    if (!resolved) {
        new Database.Collections.Users()
		    .fetch()
		    .then(function(resp) {
                if (resp != null && resp.length && resp.length > 0) {
                    for (var i = 0; i < resp.length; i++){
                        var user = resp.at(i);
                        user.cleanUp();
                        log(util.inspect(user,false,null));
                    };
                };
		        res.json(200, resp);
		        log('replied: ' + util.inspect(resp, false, null));
		    });
    };
};
UserController.getUser = function(req, res) {
	log('GetUser: ' + req.originalUrl);
	new Database.Models.User({user_id: req.params.id})
		.fetch()
		.then(function(resp) {
			res.json(200, resp);
			log('replied: ' + util.inspect(resp,false,null));
		});
};
UserController.postUserSelf = function(req, res) {
	log('PostUser: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
	if (req.body) {
		if (req.body.login && req.body.login.length <= 0) {
            req.body.login = null;
			delete req.body.login;
		};
		if (req.body.password && req.body.password.length <= 0) {
             req.body.password = null;
			delete req.body.password;
		};
		if (req.body.user_id && req.body.user_id <= 0) {
            req.body.user_id = null;
			delete req.body.user_id;
		};
		if ((!req.body.user_id && !req.body.login) || (req.body.user_id != req.session.user.user_id)) {
			res.send(500,null);
		} else {
            req.body.login = req.body.login.toLowerCase();
            new Database.Models.User({user_id: req.body.user_id})
				.fetch()
				.then(function(resp) {
                    if (resp != null) {
                        if (req.body.password && req.body.newpassword && req.body.password == resp.get('password')) {
                            if (req.body.newpassword.length > 5 && req.body.newpassword2 && req.body.newpassword == req.body.newpassword2) {
                                resp.set('password',req.body.newpassword);
                            };
                        };
                        if (req.body.email && req.body.email.length > 6) {
                            resp.set('email',req.body.email);
                        };
                        resp.set('updated_at',moment().format(moment.application_dateformat));
                        resp
                        .save()
                        .then(function(resp){
                            if (resp != null) {
                                resp.cleanUp();
                            };
					        res.json(200, resp);
					        log('replied: ' + util.inspect(resp, false, null));
                        });
	                } else {
		                res.send(500,null);
	                };
				});
		};
	} else {
		res.send(500,null);
	};
};

randPass= function(length,current){
    current = current || '';
    return length ? randPass( --length , "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt( Math.floor( Math.random() * 60 ) ) + current ) : current;
};

UserController.postUser = function(req, res) {
	log('PostUser: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
    if (req.session.user.role < Router.Access.Admin) {
        res.send(401,null);
    } else {
	    if (req.body) {
		    if (req.body.login && req.body.login.length <= 0) {
                req.body.login = null;
			    delete req.body.login;
		    };
		    if (req.body.password != null) {
                req.body.password = null;
			    delete req.body.password;
		    };
		    if (req.body.user_id && req.body.user_id <= 0) {
                req.body.user_id = null;
			    delete req.body.user_id;
		    };
		    if (!req.body.login) {
			    res.send(500,null);
		    } else {
                req.body.login = req.body.login.toLowerCase();
                var newpass = false;
                if (!req.body.user_id || req.body.user_id <= 0 || req.body.reset) {
                    if (req.body.reset) { delete req.body.reset; };
                    req.body.password = randPass(6);
                    newpass = true;
                };
                if (req.body.user_id > 0) {
                    // Existing user, we load it and update it
			        new Database.Models.User({user_id: req.body.user_id})
                        .fetch()
                        .then(function(resp) {
                            if (resp != null) {
                                req.body.updated_at = moment().format(moment.application_dateformat);
                                resp.set(req.body);
                                // We prevent the role of the admin user from being changed... for obvious reasons
                                if (resp.get('user_id') == 1 || resp.get('login') == 'admin') {
                                    resp.set('role') = 8;
                                };
                                resp
				                    .save()
				                    .then(function(resp) {
                                        if (!newpass) {
                                            resp.cleanUp();
                                        };
					                    res.json(200, resp);
					                    log('replied: ' + util.inspect(resp, false, null));
				                    });
                            } else {
                                res.send(404,null);
                            };
                        });
                } else {
                    // New user directly saved to the DB
                    req.body.created_at = moment().format(moment.application_dateformat);
                    new Database.Models.User(req.body)
				        .save()
				        .then(function(resp) {
                            if (!newpass) {
                                resp.cleanUp();
                            };
					        res.json(200, resp);
					        log('replied: ' + util.inspect(resp, false, null));
				        });
                };
		    };
	    } else {
		    res.send(500,null);
	    };
    };
};
UserController.getSession = function(req, res) {
	log('GetSession: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
	log('GetSession: ' + req.originalUrl + ' : ' + util.inspect(req.query, { showHidden: true, depth: null }));
	var login = '';
	var password = '';
	if (req.query != null && req.query.login != null && req.query.password != null && (req.query.login.length > 0 && req.query.password.length > 0)) {
	    login = req.query.login;
	    password = req.query.password;
	};
	if (req.body != null && req.body.login != null && req.body.password != null && (req.body.login.length > 0 && req.body.password.length > 0)) {
	    login = req.body.login;
	    password = req.body.password;
	};

	if (login == '' || password == '') {
		res.send(500,[]);
	} else {
        login = login.toLowerCase();
	    new Database.Models.User()
		    .query(function (qb) {
		        qb.where('login', '=', login)
                    .andWhere(function() {
                        this.whereNull('is_active').orWhere('is_active', '!=', '0');
                    })
                    .andWhere(function () {
                        this.whereNull('is_blocked').orWhere('is_blocked', '!=', '1');
                    })
		    })
            .fetch()
			.then(function(resp) {
			    if (resp) {
			        log('found: ' + util.inspect(resp, false, null));
			        var pwd_fails = resp.get('pwd_fails') || 0;
			        if (password == resp.get('password')) {
			            req.session.user = resp;
			            if (pwd_fails > 0) {
			                log('password fails reset: ' + pwd_fails);
			                resp.set("pwd_fails",0);
			            };
                        resp.set("last_ip",req.connection.remoteAddress);
                        resp.set("last_connection",moment().format(moment.application_dateformat));
			        } else {
			            pwd_fails = pwd_fails + 1;
			            resp.set("pwd_fails", pwd_fails);
			            log('password fails: ' + pwd_fails);
			            if (pwd_fails >= 5) {
			                resp.set({is_blocked: true, blocked_datetime: moment().format(moment.application_dateformat)});
			                log('login blocked: ' + pwd_fails);
                        };
			            resp.save();
			            resp = null;
			            req.session.user = new Database.Models.User({ login: login, role: 0 });
			        };
			    } else {
			        req.session.user = new Database.Models.User({ login: login, role: 0 });
			    };
			    if (resp == null) {
			        res.send(404, { status: 404, type: 'Resource', message: 'Not found' });
				    log('replied: ' + util.inspect(resp, false, null));
				    log('session: ' + util.inspect(req.session.user, false, null));
			    } else {
                    resp.save().then(function(resp){
			            resp.cleanUp();
			            res.json(200, [resp]);
				        log('replied: ' + util.inspect(resp, false, null));
				        log('session: ' + util.inspect(req.session.user, false, null));
                    });
			    };
			});
	};	
};
